package jnzb.monitor;

import java.io.File;
import java.io.FileFilter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import jnzb.control.Configuration;
import jnzb.control.Controller;
import jnzb.control.events.InfoEventProcessor;

/**
 * Monitors a directory for NZBs being dropped in then adds them to the queue. <br>
 * <b>Note:</b> the auto downloader will not continue a previous download and it
 * will only queue NZBs that are added to the folder once the application has
 * started.
 * 
 * @author Rid
 * 
 */
public class DirectoryMonitor implements Runnable {
	private Controller controller;

	private boolean keepRunning = true;

	private Set<File> nzbs = new HashSet<File>();

	private Configuration config;

	private NZBFileFilter fileFilter;

	private InfoEventProcessor info;

	private static final int SLEEP_INTERVAL = 10 * 1000;

	public DirectoryMonitor(Controller controller, InfoEventProcessor info) {
		this.controller = controller;
		this.info = info;

		this.config = Configuration.getInstance();
		this.fileFilter = new NZBFileFilter();

		// Set uo initial list so we don't start downloading everything in the
		// folder on startup
		this.nzbs = getNZBList();
	}

	/**
	 * Cause the directory monitor thread to exit
	 */
	public synchronized void stop() {
		this.keepRunning = false;
		notifyAll();
	}

	@Override
	public void run() {
		// Only run if there's a folder to monitor
		String dir = config.getAutoDownloadDirectory();
		if (dir != null && dir.trim().length() > 0) {
			info.info("Auto downloader monitoring folder " + dir);
			while (this.keepRunning) {
				// Get the directory listing
				Set<File> potentialNewNZBs = getNZBList();

				// If we remove everything that we knew about from last time,
				// we're left with whats been added
				potentialNewNZBs.removeAll(nzbs);

				// If after removing everything we knew about before, there's
				// some left, these are new
				if (!potentialNewNZBs.isEmpty()) {
					// Since we're dealing in reference here, and the
					// potentialNewNZBs object has been modified, reget the list
					// in a new object to set our state in
					this.nzbs = getNZBList();

					// Add these
					Iterator<File> i = potentialNewNZBs.iterator();
					while (i.hasNext()) {
						// Queue any new ones
						File f = i.next();
						controller.loadNZBEvent(f, false);
						info.info("Auto queued NZB " + f.getName());
					}
				}
				try {
					synchronized (this) {
						wait(SLEEP_INTERVAL);
					}
				} catch (InterruptedException e) {
					// Nothing to do!
				}
			}
			info.info("Auto Downloader exiting");
		} else {
			info.info("Auto Downloader not running");
		}
	}

	/**
	 * Returns the list of NZB files in the folder
	 * 
	 * @return
	 */
	public Set<File> getNZBList() {
		Set<File> newNZBs = new HashSet<File>();

		File rootDir = new File(config.getAutoDownloadDirectory());

		File[] f = rootDir.listFiles(fileFilter);

		if (f != null)
			for (int i = 0; i < f.length; i++) {
				newNZBs.add(f[i]);
			}
		return newNZBs;
	}

	private class NZBFileFilter implements FileFilter {

		@Override
		public boolean accept(File pathname) {
			return pathname.getName().toLowerCase().endsWith("nzb");
		}

	}
}
